home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2018 January / PCgo 01-2018 CD-ROM Germany.iso / nw.pak / Unnamed File 000207.txt < prev    next >
Encoding:
Text File  |  2015-07-29  |  11.0 KB  |  352 lines

  1.  
  2.  
  3.   (function() {
  4.  
  5.     var waveMaxRadius = 150;
  6.     //
  7.     // INK EQUATIONS
  8.     //
  9.     function waveRadiusFn(touchDownMs, touchUpMs, anim) {
  10.       // Convert from ms to s
  11.       var touchDown = touchDownMs / 1000;
  12.       var touchUp = touchUpMs / 1000;
  13.       var totalElapsed = touchDown + touchUp;
  14.       var ww = anim.width, hh = anim.height;
  15.       // use diagonal size of container to avoid floating point math sadness
  16.       var waveRadius = Math.min(Math.sqrt(ww * ww + hh * hh), waveMaxRadius) * 1.1 + 5;
  17.       var duration = 1.1 - .2 * (waveRadius / waveMaxRadius);
  18.       var tt = (totalElapsed / duration);
  19.  
  20.       var size = waveRadius * (1 - Math.pow(80, -tt));
  21.       return Math.abs(size);
  22.     }
  23.  
  24.     function waveOpacityFn(td, tu, anim) {
  25.       // Convert from ms to s.
  26.       var touchDown = td / 1000;
  27.       var touchUp = tu / 1000;
  28.       var totalElapsed = touchDown + touchUp;
  29.  
  30.       if (tu <= 0) {  // before touch up
  31.         return anim.initialOpacity;
  32.       }
  33.       return Math.max(0, anim.initialOpacity - touchUp * anim.opacityDecayVelocity);
  34.     }
  35.  
  36.     function waveOuterOpacityFn(td, tu, anim) {
  37.       // Convert from ms to s.
  38.       var touchDown = td / 1000;
  39.       var touchUp = tu / 1000;
  40.  
  41.       // Linear increase in background opacity, capped at the opacity
  42.       // of the wavefront (waveOpacity).
  43.       var outerOpacity = touchDown * 0.3;
  44.       var waveOpacity = waveOpacityFn(td, tu, anim);
  45.       return Math.max(0, Math.min(outerOpacity, waveOpacity));
  46.     }
  47.  
  48.     // Determines whether the wave should be completely removed.
  49.     function waveDidFinish(wave, radius, anim) {
  50.       var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
  51.  
  52.       // If the wave opacity is 0 and the radius exceeds the bounds
  53.       // of the element, then this is finished.
  54.       return waveOpacity < 0.01 && radius >= Math.min(wave.maxRadius, waveMaxRadius);
  55.     };
  56.  
  57.     function waveAtMaximum(wave, radius, anim) {
  58.       var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
  59.  
  60.       return waveOpacity >= anim.initialOpacity && radius >= Math.min(wave.maxRadius, waveMaxRadius);
  61.     }
  62.  
  63.     //
  64.     // DRAWING
  65.     //
  66.     function drawRipple(ctx, x, y, radius, innerAlpha, outerAlpha) {
  67.       // Only animate opacity and transform
  68.       if (outerAlpha !== undefined) {
  69.         ctx.bg.style.opacity = outerAlpha;
  70.       }
  71.       ctx.wave.style.opacity = innerAlpha;
  72.  
  73.       var s = radius / (ctx.containerSize / 2);
  74.       var dx = x - (ctx.containerWidth / 2);
  75.       var dy = y - (ctx.containerHeight / 2);
  76.  
  77.       ctx.wc.style.webkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0)';
  78.       ctx.wc.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0)';
  79.  
  80.       // 2d transform for safari because of border-radius and overflow:hidden clipping bug.
  81.       // https://bugs.webkit.org/show_bug.cgi?id=98538
  82.       ctx.wave.style.webkitTransform = 'scale(' + s + ',' + s + ')';
  83.       ctx.wave.style.transform = 'scale3d(' + s + ',' + s + ',1)';
  84.     }
  85.  
  86.     //
  87.     // SETUP
  88.     //
  89.     function createWave(elem) {
  90.       var elementStyle = window.getComputedStyle(elem);
  91.       var fgColor = elementStyle.color;
  92.  
  93.       var inner = document.createElement('div');
  94.       inner.style.backgroundColor = fgColor;
  95.       inner.classList.add('wave');
  96.  
  97.       var outer = document.createElement('div');
  98.       outer.classList.add('wave-container');
  99.       outer.appendChild(inner);
  100.  
  101.       var container = elem.$.waves;
  102.       container.appendChild(outer);
  103.  
  104.       elem.$.bg.style.backgroundColor = fgColor;
  105.  
  106.       var wave = {
  107.         bg: elem.$.bg,
  108.         wc: outer,
  109.         wave: inner,
  110.         waveColor: fgColor,
  111.         maxRadius: 0,
  112.         isMouseDown: false,
  113.         mouseDownStart: 0.0,
  114.         mouseUpStart: 0.0,
  115.         tDown: 0,
  116.         tUp: 0
  117.       };
  118.       return wave;
  119.     }
  120.  
  121.     function removeWaveFromScope(scope, wave) {
  122.       if (scope.waves) {
  123.         var pos = scope.waves.indexOf(wave);
  124.         scope.waves.splice(pos, 1);
  125.         // FIXME cache nodes
  126.         wave.wc.remove();
  127.       }
  128.     };
  129.  
  130.     // Shortcuts.
  131.     var pow = Math.pow;
  132.     var now = Date.now;
  133.     if (window.performance && performance.now) {
  134.       now = performance.now.bind(performance);
  135.     }
  136.  
  137.     function cssColorWithAlpha(cssColor, alpha) {
  138.         var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
  139.         if (typeof alpha == 'undefined') {
  140.             alpha = 1;
  141.         }
  142.         if (!parts) {
  143.           return 'rgba(255, 255, 255, ' + alpha + ')';
  144.         }
  145.         return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')';
  146.     }
  147.  
  148.     function dist(p1, p2) {
  149.       return Math.sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
  150.     }
  151.  
  152.     function distanceFromPointToFurthestCorner(point, size) {
  153.       var tl_d = dist(point, {x: 0, y: 0});
  154.       var tr_d = dist(point, {x: size.w, y: 0});
  155.       var bl_d = dist(point, {x: 0, y: size.h});
  156.       var br_d = dist(point, {x: size.w, y: size.h});
  157.       return Math.max(tl_d, tr_d, bl_d, br_d);
  158.     }
  159.  
  160.     Polymer('paper-ripple', {
  161.  
  162.       /**
  163.        * The initial opacity set on the wave.
  164.        *
  165.        * @attribute initialOpacity
  166.        * @type number
  167.        * @default 0.25
  168.        */
  169.       initialOpacity: 0.25,
  170.  
  171.       /**
  172.        * How fast (opacity per second) the wave fades out.
  173.        *
  174.        * @attribute opacityDecayVelocity
  175.        * @type number
  176.        * @default 0.8
  177.        */
  178.       opacityDecayVelocity: 0.8,
  179.  
  180.       backgroundFill: true,
  181.       pixelDensity: 2,
  182.  
  183.       eventDelegates: {
  184.         down: 'downAction',
  185.         up: 'upAction'
  186.       },
  187.  
  188.       ready: function() {
  189.         this.waves = [];
  190.       },
  191.  
  192.       downAction: function(e) {
  193.         var wave = createWave(this);
  194.  
  195.         this.cancelled = false;
  196.         wave.isMouseDown = true;
  197.         wave.tDown = 0.0;
  198.         wave.tUp = 0.0;
  199.         wave.mouseUpStart = 0.0;
  200.         wave.mouseDownStart = now();
  201.  
  202.         var rect = this.getBoundingClientRect();
  203.         var width = rect.width;
  204.         var height = rect.height;
  205.         var touchX = e.x - rect.left;
  206.         var touchY = e.y - rect.top;
  207.  
  208.         wave.startPosition = {x:touchX, y:touchY};
  209.  
  210.         if (this.classList.contains("recenteringTouch")) {
  211.           wave.endPosition = {x: width / 2,  y: height / 2};
  212.           wave.slideDistance = dist(wave.startPosition, wave.endPosition);
  213.         }
  214.         wave.containerSize = Math.max(width, height);
  215.         wave.containerWidth = width;
  216.         wave.containerHeight = height;
  217.         wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height});
  218.  
  219.         // The wave is circular so constrain its container to 1:1
  220.         wave.wc.style.top = (wave.containerHeight - wave.containerSize) / 2 + 'px';
  221.         wave.wc.style.left = (wave.containerWidth - wave.containerSize) / 2 + 'px';
  222.         wave.wc.style.width = wave.containerSize + 'px';
  223.         wave.wc.style.height = wave.containerSize + 'px';
  224.  
  225.         this.waves.push(wave);
  226.  
  227.         if (!this._loop) {
  228.           this._loop = this.animate.bind(this, {
  229.             width: width,
  230.             height: height
  231.           });
  232.           requestAnimationFrame(this._loop);
  233.         }
  234.         // else there is already a rAF
  235.       },
  236.  
  237.       upAction: function() {
  238.         for (var i = 0; i < this.waves.length; i++) {
  239.           // Declare the next wave that has mouse down to be mouse'ed up.
  240.           var wave = this.waves[i];
  241.           if (wave.isMouseDown) {
  242.             wave.isMouseDown = false
  243.             wave.mouseUpStart = now();
  244.             wave.mouseDownStart = 0;
  245.             wave.tUp = 0.0;
  246.             break;
  247.           }
  248.         }
  249.         this._loop && requestAnimationFrame(this._loop);
  250.       },
  251.  
  252.       cancel: function() {
  253.         this.cancelled = true;
  254.       },
  255.  
  256.       animate: function(ctx) {
  257.         var shouldRenderNextFrame = false;
  258.  
  259.         var deleteTheseWaves = [];
  260.         // The oldest wave's touch down duration
  261.         var longestTouchDownDuration = 0;
  262.         var longestTouchUpDuration = 0;
  263.         // Save the last known wave color
  264.         var lastWaveColor = null;
  265.         // wave animation values
  266.         var anim = {
  267.           initialOpacity: this.initialOpacity,
  268.           opacityDecayVelocity: this.opacityDecayVelocity,
  269.           height: ctx.height,
  270.           width: ctx.width
  271.         }
  272.  
  273.         for (var i = 0; i < this.waves.length; i++) {
  274.           var wave = this.waves[i];
  275.  
  276.           if (wave.mouseDownStart > 0) {
  277.             wave.tDown = now() - wave.mouseDownStart;
  278.           }
  279.           if (wave.mouseUpStart > 0) {
  280.             wave.tUp = now() - wave.mouseUpStart;
  281.           }
  282.  
  283.           // Determine how long the touch has been up or down.
  284.           var tUp = wave.tUp;
  285.           var tDown = wave.tDown;
  286.           longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown);
  287.           longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp);
  288.  
  289.           // Obtain the instantenous size and alpha of the ripple.
  290.           var radius = waveRadiusFn(tDown, tUp, anim);
  291.           var waveAlpha =  waveOpacityFn(tDown, tUp, anim);
  292.           var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha);
  293.           lastWaveColor = wave.waveColor;
  294.  
  295.           // Position of the ripple.
  296.           var x = wave.startPosition.x;
  297.           var y = wave.startPosition.y;
  298.  
  299.           // Ripple gravitational pull to the center of the canvas.
  300.           if (wave.endPosition) {
  301.  
  302.             // This translates from the origin to the center of the view  based on the max dimension of
  303.             var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) );
  304.  
  305.             x += translateFraction * (wave.endPosition.x - wave.startPosition.x);
  306.             y += translateFraction * (wave.endPosition.y - wave.startPosition.y);
  307.           }
  308.  
  309.           // If we do a background fill fade too, work out the correct color.
  310.           var bgFillColor = null;
  311.           if (this.backgroundFill) {
  312.             var bgFillAlpha = waveOuterOpacityFn(tDown, tUp, anim);
  313.             bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha);
  314.           }
  315.  
  316.           // Draw the ripple.
  317.           drawRipple(wave, x, y, radius, waveAlpha, bgFillAlpha);
  318.  
  319.           // Determine whether there is any more rendering to be done.
  320.           var maximumWave = waveAtMaximum(wave, radius, anim);
  321.           var waveDissipated = waveDidFinish(wave, radius, anim);
  322.           var shouldKeepWave = !waveDissipated || maximumWave;
  323.           // keep rendering dissipating wave when at maximum radius on upAction
  324.           var shouldRenderWaveAgain = wave.mouseUpStart ? !waveDissipated : !maximumWave;
  325.           shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain;
  326.           if (!shouldKeepWave || this.cancelled) {
  327.             deleteTheseWaves.push(wave);
  328.           }
  329.        }
  330.  
  331.         if (shouldRenderNextFrame) {
  332.           requestAnimationFrame(this._loop);
  333.         }
  334.  
  335.         for (var i = 0; i < deleteTheseWaves.length; ++i) {
  336.           var wave = deleteTheseWaves[i];
  337.           removeWaveFromScope(this, wave);
  338.         }
  339.  
  340.         if (!this.waves.length && this._loop) {
  341.           // clear the background color
  342.           this.$.bg.style.backgroundColor = null;
  343.           this._loop = null;
  344.           this.fire('core-transitionend');
  345.         }
  346.       }
  347.  
  348.     });
  349.  
  350.   })();
  351.  
  352.